<?php
/**
 * 后台菜单管理
 * 
 * 菜单排序、菜单编辑、添加子菜单、菜单删除等
 */
namespace app\admin\controller;

use think\Request;
use category\CategoryContext;
// use category\CategoriesMenuManager;
use category\CategoriesMenuManagerJsGrip;
use messagestack\messageStack;

class Menu extends AdminBase
{
    /**
     * 菜单列表展示
     */
    function index(Request $request)
    {
        // $object = new CategoriesMenuManager( $this->menuData );
        // jsGrip风格
        $object = new CategoriesMenuManagerJsGrip( $this->menuData );
        $menus = new CategoryContext($object);
        // 菜单列表展示
        $this->assign('menu_list', $menus->getResult());
        return $this->fetch();
    }

    /**
     * 菜单编辑
     */
    function edit(Request $request)
    {
        // 只接受PUT请求
        if ($request->isPut())
        {
            $messageStack = new messageStack();
            $menu_item    = $request->param();
            $admin_menu   = model('AdminMenus');
            $menu         = $admin_menu->getOneData([ 'id' => $menu_item['id'] ]);
            // 在尚未更新后台菜单表时，先获取其url字段
            $old_menu_url = $menu->url;
            // 表单数据验证
            $validate     = validate('AdminMenus');
            if (!$validate->scene('edit')->batch()->check( $menu_item ))
            {
                foreach ($validate->getError() as $error_msg)
                {
                    $messageStack->add('edit', $error_msg);
                }
            } else {
                // 如果出现了非数据表字段数据，allowField会抛出错误，
                // 但是用动态配置无法改fields_strict(除非在第一次model('AdminMenus')之前改才有效)，
                // 所以下面这个写法无效
                // $admin_menu->allowField(true)->editData($menu_item, [ 'id' => $menu_item['id'] ]);
                // 根据给定菜单项更新后台菜单表
                $admin_menu->allowField(true)->strict(false)->where('id', '=', $menu_item['id'])->update($menu_item);
            
                $auth_rule = model('AuthRule');
                $result = $auth_rule->getOneData([ 'name' => $menu_item['url'] ]);
                // 如果要更新的菜单项不在身份验证规则表里
                if (empty($result))
                {
                    // 如果要更新的菜单项不在身份验证规则表里，则：
                    $old_result = $auth_rule->getOneData(['name' => $old_menu_url]);
                    // 菜单项真的不在身份验证规则表里，则在此表新增一条
                    if ( empty($old_result) )
                    {
                        $data = [
                            'name'   => $menu_item['url'],
                            'title'  => $menu_item['title'],
                            'status' => $menu_item['status'],
                        ];
                        $auth_rule->addData($data);
                    } else {
                        // 否则菜单的控制器/方法已被更改，则更新身份验证规则表
                        $data = [
                            'name'   => $menu_item['url'],
                            'title'  => $menu_item['title'],
                            'status' => $menu_item['status'],
                        ];
                        $where = ['name' => $old_menu_url];
                        $auth_rule->editData($data, $where);
                    }

                } else {
                    // 更新与菜单项对应的身份验证规则
                    $data = [
                        'title'  => $menu_item['title'],
                        'status' => $menu_item['status'],
                    ];
                    $where = [ 'name' => $menu_item['url'] ];
                    $auth_rule->editData($data, $where);
                }
                
                cache('menu_data', null);
                $this->success(lang('EDIT_SUCCESS'), '', 
                    [
                        'id'     => $menu_item['id'], 
                        'pid'    => $menu_item['pid'],
                        'title'  => $menu_item['title'], 
                        'url'    => $menu_item['url'], 
                        'status' => $menu_item['status'], 
                        'sort'   => $menu_item['sort'],
                        'level'  => $menu_item['level'],
                        'icon'   => $menu_item['icon']
                    ]
                );
            }
           
            if ($messageStack->size('edit'))
            {
                $output = '';
                foreach ($messageStack->output('edit') as $message)
                {
                    $output .= $message;
                }
                
                $this->error($output, '', [
                    'id'     => $menu['id'], 
                    'pid'    => $menu['pid'],
                    'title'  => $menu['title'], 
                    'url'    => $menu['url'], 
                    'status' => $menu['status'], 
                    'sort'   => $menu['sort'],
                    'icon'   => $menu['icon'],
                    'level'  => $menu_item['level']
                ]);
            }
        }
        return '';
    }

    /**
     * 菜单删除
     */
    function delete(Request $request)
    {
        $id           = $request->param('id', 0, 'intval');
        $admin_menu   = model('AdminMenus');
        $sub_menu     = $admin_menu->getSubAdminMenus($id);
        $messageStack = new messageStack();
        $result       = [];

        /**
         * 由于请求方式不是ajax(比如为fetch)，TP不能自动返回json格式的数据
         * 所以要显式的设置返回内容格式为JSON
         * 
         * 用AJAX请求伪装可不用配置此选项
         */
        config('default_return_type', 'json');

        // 检查是否有子菜单，如果有，则提示不能删
        if (!empty($sub_menu))
        {
            $messageStack->add('delete', lang('A_SUBMENU_ERROR'));
            $msg = array_reduce($messageStack->output('delete'), function($v1, $v2) {
                       return $v1 . $v2;
                   });
            $result = [
                'code' => 0,
                'msg'  => $msg,
            ];
        } else {
            // 如果没有子菜单，则删除数据库里的菜单项，并提示删除成功
            if ($admin_menu->deleteData(['id' => $id]))
            {
                $result = [
                    'code' => 1,
                    'msg'  => lang('DELETE_MENU_SUCCESS'),
                ];
                cache('menu_data', null);
            } else {
                $result = [
                    'code' => 0,
                    'msg'  => lang('DELETE_MENU_ERROR'),
                ];
            }
        }
        // 返回json实例便可输出json格式的数据到客户端,改配置不是好选择
        // reutrn json($result)
        return json_encode($result);
    }
}